﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Draco.OWF.Repository.Factory
{
    internal class NamedType
    {
        private static Dictionary<String, String> m_NamedTypeNames = new Dictionary<string, string>();
        private static Dictionary<String, Type> m_NamedTypes = new Dictionary<string, Type>();

        static NamedType()
        {
            String assemblyName = typeof(NamedType).Assembly.FullName;
            m_NamedTypeNames.Add("Activity.EmptyActivity", "Draco.OWF.Acticity.EmptyActivity," + assemblyName);
            m_NamedTypeNames.Add("Activity.InvokerActivity", "Draco.OWF.Acticity.General.InvokerActivity," + assemblyName);
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="shortType"></param>
        /// <returns></returns>
        public static String GetNamedTypeFullName(String shortType)
        {
            String fullType = m_NamedTypeNames[shortType];
            return String.IsNullOrEmpty(fullType) ? shortType : fullType;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="shortType"></param>
        /// <returns></returns>
        public static Type GetNamedType(String shortType)
        {
            String fullTypeName = GetNamedTypeFullName(shortType);
            Type type = m_NamedTypes[fullTypeName];
            if (type == null && !String.IsNullOrEmpty(fullTypeName))
            {
                String typeName = ParseTypeName(fullTypeName);
                AssemblyName assemblyName = ParseAssemblyName(fullTypeName);
                if (String.IsNullOrEmpty(typeName))
                    throw new ArgumentException("can't parse type name from :" + fullTypeName);
                if (assemblyName==null)
                    throw new ArgumentException("can't parse assembly name from :" + fullTypeName);
                Assembly assembly = GetAssembly(assemblyName);
                type = assembly.GetType(typeName, false, true);
                m_NamedTypes[fullTypeName] = type;
            }
            return type;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fullTypeName">like this:System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</param>
        /// <returns></returns>
        private static String ParseTypeName(String fullTypeName)
        {
            int index = fullTypeName.IndexOf(",");
            if (index > 0)
                return fullTypeName.Substring(0, index).Trim();
            return "";
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fullTypeName">like this:System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</param>
        /// <returns></returns>
        private static AssemblyName ParseAssemblyName(String fullTypeName)
        {
            String name="";
            int index = fullTypeName.IndexOf(",");
            if (index > 0 && index < fullTypeName.Length-1)
            {
                name = fullTypeName.Substring(index + 1).Trim();
            }
            try
            {
                return new AssemblyName(name);
            }
            catch { }
            return null;
        }

        private static Assembly GetAssembly(AssemblyName assemblyName)
        {
            //find it from current domain
            Assembly[] allass = System.AppDomain.CurrentDomain.GetAssemblies();
            for (int i = 0; i < allass.Length; i++)
            {
                if (allass[i].FullName == assemblyName.FullName)
                {
                    return allass[i];
                }
            }
            //can't find it
            try
            {
                //reflect to load it
                Assembly assb = Assembly.Load(assemblyName);
                return assb;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }
}
